import * as fse from "fs-extra";
import path from "path";
import * as xml2js from "xml2js";
import { projCfg } from "../../projCfg";
import { cmd_base } from './cmd_base';

/** 标签属性接口 */
interface ITag {
    /** 定义的消息id  只有message才有 */
    id: string,
    /** 数据类型 如list message里是CS SC */
    type: string;
    /** 数据结构类型 */
    class: string;
    /** map key */
    keyclass: string;
    /** map值 */
    valueclass: string;
    /** map数组 */
    valuelist: string;
    /** 名称 */
    name: string;
    /** 注释 */
    comment: string;
}
/** 标签属性接口 */
interface IProperty {
    /** 属性 */
    $: ITag;
}
/** 消息、数据 结构类型定义接口 */
interface IMessage {
    /** 属性 */
    $: ITag;
    /** 字段list */
    field: IProperty[];
}
interface IXml {
    /** package的属性 */
    $: ITag,
    /** 数据结构 */
    bean: IMessage[],
    /** 消息接口 */
    message: IMessage[],
}
/** 数据结构 */
interface IXmlData {
    package: IXml;
}
export class cmd_ds extends cmd_base {
    /** 消息id-key map */
    m2sMap = "";
    /** 字段：[field:type] */
    s2fMap = "";
    /** 消息接口 */
    message = "";
    /** 消息id接口 */
    messageId = "";
    async run() {
        let itself = this;
        let xmlFiles = fse.readdirSync(projCfg.xmlSrcPath);
        for (let index = 0, len = xmlFiles.length; index < len; index++) {
            let fileName = xmlFiles[index];
            let nameSuffix = fileName.split(".");
            if (nameSuffix[1] != "xml") {
                continue;
            }
            let filePath = path.join(projCfg.xmlSrcPath, fileName);
            await itself.readXml(filePath);
        }
        //写入文件
        itself.message = `export namespace msg {\n${itself.message}}`;
        fse.ensureDirSync(projCfg.xmlOutPath);
        fse.writeFile(path.join(projCfg.xmlOutPath, "msg.ts"), itself.message);

        itself.m2sMap = `god.m2sMap = {\n${itself.m2sMap}};\n`;
        itself.s2fMap = `god.s2fMap = {\n${itself.s2fMap}};`;
        let tempStr = itself.m2sMap + itself.s2fMap;
        fse.writeFile(path.join(projCfg.xmlOutPath, "map.ts"), tempStr);

        itself.messageId = `export const enum msgId {\n${itself.messageId}}`;
        fse.writeFile(path.join(projCfg.xmlOutPath, "msgId.ts"), itself.messageId);
    }
    /** 读取文件 */
    async readXml(filePath: string) {
        let itself = this;
        let fieldata = fse.readFileSync(filePath);
        let xmlName = path.basename(filePath);
        let result: IXmlData = await new Promise(function (resolve, reject) {
            xml2js.parseString(fieldata, (error: Error, result: IXmlData) => {
                if (error) {
                    console.error(error);
                    return;
                }
                resolve(result);
            })
        })
        itself.parserXml(result, xmlName);

    }
    /** 解析文件 */
    parserXml(result: IXmlData, xmlName: string) {
        let itself = this;
        let packages = result?.package?.$;
        if (!packages) {
            console.error(`${xmlName}文件没配置package`);
            return;
        }
        let bean = result?.package?.bean;
        let message = result?.package?.message;
        if (bean) {
            for (let index = 0, len = bean.length; index < len; index++) {
                let content = bean[index];
                let beanProp = content.$;
                if (!beanProp.name) {
                    console.error(`${xmlName}文件bean标签没配置name`);
                    return;
                }
                itself.s2fMap += `\t"${beanProp.name}": [\n`;
                itself.message += `\t/** ${content.$.comment} */\n\texport interface ${beanProp.name} {\n`;
                let len = content.field?.length || 0;
                for (let indexfield = 0; indexfield < len; indexfield++) {
                    let field = content.field[indexfield].$;
                    if (field) {
                        let tempType = itself.getShowType(field.class);
                        let type = field.type == "list" ? `"${tempType}", 1` : `"${tempType}"`
                        itself.s2fMap += `\t\t["${field.name}", ${type}],\n`;
                        itself.message += `\t\t/** ${field.comment} */\n\t\t${field.name}?: ${itself.getFieldType(itself.getXmlFieldType(field))};\n`;
                    }
                }
                itself.message += `\t}\n`;
                itself.s2fMap += `\t],\n`;
            }
        }
        if (message) {
            for (let index = 0, len = message.length; index < len; index++) {
                let content = message[index];
                let messageProp = content.$;
                if (!messageProp.name || !messageProp.id) {
                    console.error(`${xmlName}文件message标签没配置name或者id`);
                    return;
                }
                itself.s2fMap += `\t"${messageProp.name}": [\n`;
                itself.m2sMap += `\t"${messageProp.id}": "${messageProp.name}",\n`;
                itself.messageId += `\t/** 消息Id-${messageProp.comment} */\n`
                itself.messageId += `\t${messageProp.name} = ${messageProp.id},\n`;
                itself.message += `\t/** ${content.$.comment} */\n\texport interface ${messageProp.name} {\n`;
                let len = content.field?.length || 0;
                for (let indexfield = 0; indexfield < len; indexfield++) {
                    let field = content.field[indexfield].$;
                    if (field) {
                        let tempType = itself.getShowType(field.class);
                        let type = field.type == "list" ? `"${tempType}", 1` : `"${tempType}"`
                        itself.s2fMap += `\t\t["${field.name}", ${type}],\n`;
                        itself.message += `\t\t/** ${field.comment} */\n\t\t${field.name}?: ${itself.getFieldType(itself.getXmlFieldType(field))};\n`;
                    }
                }
                itself.message += `\t}\n`;
                itself.s2fMap += `\t],\n`;
            }
        }
    }
    /** 获取xxx.xxx.IXXX中的IXXX */
    getShowType(type: string) {
        if (type.indexOf(".") >= 0) {
            let splitType = type.split(".")
            type = splitType[splitType.length - 1];
        }
        return type;
    }
    /** 字段自定义类型转换 */
    getXmlFieldType(field: ITag) {
        let itself = this;
        let type = field.class;
        type = itself.getShowType(type);
        if (type == "map") {
            if (field.valuelist == "true") {
                type = `{ [key: ${itself.getFieldType(field.keyclass)}]: ${itself.getFieldType(field.valueclass)}[] }`;
            } else {
                type = `{ [key: ${itself.getFieldType(field.keyclass)}]: ${itself.getFieldType(field.valueclass)} }`;
            }
        }
        if (field.type == "list") {
            type = `${type}[]`;
        }
        return type;
    }
}
new cmd_ds().run();